package com.inexas.cu.client.mvp;

import java.util.*;
import com.inexas.cu.client.mvp.ListNotification.*;

public class PropertyListImpl<T> extends MemberImpl implements PropertyList<T> {
	// Note: ArrayList not List for GWT client performance
	private final ArrayList<T> list = new ArrayList<T>();

	public PropertyListImpl(String key) {
		super(key);
    }

	/* (non-Javadoc)
     * @see com.inexas.cu.client.mvp.PropertyList#add(com.inexas.cu.client.mvp.Source, T)
     */
	public boolean add(Source source, T element) {
		final ListNotification notification = new ListNotification(Type.INSERT, list.size(), 1);
		list.add(element);
		fire(source, notification);
		return true;
	}

	/* (non-Javadoc)
     * @see com.inexas.cu.client.mvp.PropertyList#add(com.inexas.cu.client.mvp.Source, int, T)
     */
	public void add(Source source, int index, T element) {
		final ListNotification notification = new ListNotification(Type.INSERT, index, 1);
		list.add(index, element);
		fire(source, notification);
	}

	/* (non-Javadoc)
     * @see com.inexas.cu.client.mvp.PropertyList#addAll(com.inexas.cu.client.mvp.Source, java.util.Collection)
     */
	public boolean addAll(Source source, Collection<T> collection) {
		final boolean result;
		if(collection.size() > 0) {
			final ListNotification notification = new ListNotification(	//
					Type.INSERT,	//
					list.size(),	//
					collection.size());
			list.addAll(collection);
			fire(source, notification);
			result = true;
		} else {
			result = false;
		}
		return result;
	}

	/* (non-Javadoc)
     * @see com.inexas.cu.client.mvp.PropertyList#addAll(com.inexas.cu.client.mvp.Source, int, java.util.Collection)
     */
	public boolean addAll(Source source, int index, Collection<T> collection) {
		final boolean result;
		if(collection.size() > 0) {
			final ListNotification notification = new ListNotification(	//
					Type.INSERT,	//
					index,	//
					collection.size());
			list.addAll(index, collection);
			fire(source, notification);
			result = true;
		} else {
			result = false;
		}
		return result;
	}

	/* (non-Javadoc)
     * @see com.inexas.cu.client.mvp.PropertyList#clear(com.inexas.cu.client.mvp.Source)
     */
	public void clear(Source source) {
		if(list.size() > 0) {
			final ListNotification notification = new ListNotification(Type.DELETE,	0, list.size());
			list.clear();
			fire(source, notification);
		}
	}

	/* (non-Javadoc)
     * @see com.inexas.cu.client.mvp.PropertyList#remove(com.inexas.cu.client.mvp.Source, T)
     */
	public boolean remove(Source source, T element) {
		final boolean result;
		final int index = list.indexOf(element);
		if(index >= 0) {
			final ListNotification notification = new ListNotification(Type.DELETE,	index, 1);
			list.remove(index);
			fire(source, notification);
			result = true;
		} else {
			result = false;
		}
		return result;
	}

	/* (non-Javadoc)
     * @see com.inexas.cu.client.mvp.PropertyList#remove(com.inexas.cu.client.mvp.Source, int)
     */
	public T remove(Source source, int index) {
		final ListNotification notification = new ListNotification(Type.DELETE,	index, 1);
		final T result = list.remove(index);
		fire(source, notification);
		return result;
	}

	/* (non-Javadoc)
     * @see com.inexas.cu.client.mvp.PropertyList#removeAll(com.inexas.cu.client.mvp.Source, java.util.Collection)
     */
	public boolean removeAll(Source source, Collection<T> collection) {
		final boolean result = list.removeAll(collection);
		if(result) {
			final ListNotification notification = new ListNotification(Type.RESET, 0, list.size());
			fire(source, notification);
		}
		return result;
	}

	/* (non-Javadoc)
     * @see com.inexas.cu.client.mvp.PropertyList#retainAll(com.inexas.cu.client.mvp.Source, java.util.Collection)
     */
	public boolean retainAll(Source source, Collection<T> collection) {
		final boolean result = list.retainAll(collection);
		if(result) {
			final ListNotification notification = new ListNotification(Type.RESET, 0, list.size());
			fire(source, notification);
		}
		return result;
	}

	// Non-mutator methods...

	/* (non-Javadoc)
     * @see com.inexas.cu.client.mvp.PropertyList#contains(T)
     */
	public boolean contains(T element) {
		return list.contains(element);
	}

	/* (non-Javadoc)
     * @see com.inexas.cu.client.mvp.PropertyList#containsAll(java.util.Collection)
     */
	public boolean containsAll(Collection<T> collection) {
		return list.containsAll(collection);
	}

	/* (non-Javadoc)
     * @see com.inexas.cu.client.mvp.PropertyList#get(int)
     */
	public T get(int index) {
		return list.get(index);
	}

	/* (non-Javadoc)
     * @see com.inexas.cu.client.mvp.PropertyList#indexOf(T)
     */
	public int indexOf(T element) {
		return list.indexOf(element);
	}

	/* (non-Javadoc)
     * @see com.inexas.cu.client.mvp.PropertyList#isEmpty()
     */
	public boolean isEmpty() {
		return list.isEmpty();
	}

	/* (non-Javadoc)
     * @see com.inexas.cu.client.mvp.PropertyList#iterator()
     */
	public Iterator<T> iterator() {
		// !todo Consider making this return an unmodifiable set
		return list.iterator();
	}

	/* (non-Javadoc)
     * @see com.inexas.cu.client.mvp.PropertyList#lastIndexOf(T)
     */
	public int lastIndexOf(T element) {
		return lastIndexOf(element);
	}

	/* (non-Javadoc)
     * @see com.inexas.cu.client.mvp.PropertyList#listIterator()
     */
	public ListIterator<T> listIterator() {
		// !todo Consider making this return an unmodifiable set
		return list.listIterator();
	}

	/* (non-Javadoc)
     * @see com.inexas.cu.client.mvp.PropertyList#listIterator(int)
     */
	public ListIterator<T> listIterator(int index) {
		// !todo Consider making this return an unmodifiable set
		return list.listIterator(index);
	}

	/* (non-Javadoc)
     * @see com.inexas.cu.client.mvp.PropertyList#set(int, T)
     */
	public T set(int index, T element) {
		return list.set(index, element);
	}

	/* (non-Javadoc)
     * @see com.inexas.cu.client.mvp.PropertyList#size()
     */
	public int size() {
		return list.size();
	}

    /* (non-Javadoc)
     * @see com.inexas.cu.client.mvp.PropertyList#toArray()
     */
    public T[] toArray() {
    	@SuppressWarnings("unchecked")
		final T[] result = (T[])new Object[list.size()];
		return list.toArray(result);
	}

}
